{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "Ic4_occAAiAT"
      },
      "source": [
        "##### Copyright 2019 The TensorFlow Authors."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "cellView": "form",
        "id": "ioaprt5q5US7"
      },
      "outputs": [],
      "source": [
        "#@title Licensed under the Apache License, Version 2.0 (the \"License\");\n",
        "# you may not use this file except in compliance with the License.\n",
        "# You may obtain a copy of the License at\n",
        "#\n",
        "# https://www.apache.org/licenses/LICENSE-2.0\n",
        "#\n",
        "# Unless required by applicable law or agreed to in writing, software\n",
        "# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
        "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
        "# See the License for the specific language governing permissions and\n",
        "# limitations under the License."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "cellView": "form",
        "id": "yCl0eTNH5RS3"
      },
      "outputs": [],
      "source": [
        "#@title MIT License\n",
        "#\n",
        "# Copyright (c) 2017 François Chollet\n",
        "#\n",
        "# Permission is hereby granted, free of charge, to any person obtaining a\n",
        "# copy of this software and associated documentation files (the \"Software\"),\n",
        "# to deal in the Software without restriction, including without limitation\n",
        "# the rights to use, copy, modify, merge, publish, distribute, sublicense,\n",
        "# and/or sell copies of the Software, and to permit persons to whom the\n",
        "# Software is furnished to do so, subject to the following conditions:\n",
        "#\n",
        "# The above copyright notice and this permission notice shall be included in\n",
        "# all copies or substantial portions of the Software.\n",
        "#\n",
        "# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n",
        "# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n",
        "# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n",
        "# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n",
        "# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n",
        "# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n",
        "# DEALINGS IN THE SOFTWARE."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "ItXfxkxvosLH"
      },
      "source": [
        "# Klasifikasi Teks dengan TensorFlow Hub: Review Movie"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "hKY4XMc9o8iB"
      },
      "source": [
        "<table class=\"tfo-notebook-buttons\" align=\"left\">\n",
        "  <td>\n",
        "    <a target=\"_blank\" href=\"https://www.tensorflow.org/tutorials/keras/text_classification_with_hub\"><img src=\"https://www.tensorflow.org/images/tf_logo_32px.png\" />Lihat di TensorFlow.org</a>\n",
        "  </td>\n",
        "  <td>\n",
        "    <a target=\"_blank\" href=\"https://colab.research.google.com/github/tensorflow/docs-l10n/blob/master/site/id/tutorials/keras/text_classification_with_hub.ipynb\"><img src=\"https://www.tensorflow.org/images/colab_logo_32px.png\" />Jalankan di Google Colab</a>\n",
        "  </td>\n",
        "  <td>\n",
        "    <a target=\"_blank\" href=\"https://github.com/tensorflow/docs-l10n/blob/master/site/id/tutorials/keras/text_classification_with_hub.ipynb\"><img src=\"https://www.tensorflow.org/images/GitHub-Mark-32px.png\" />Lihat sumber kode di GitHub</a>\n",
        "  </td>\n",
        "  <td>\n",
        "    <a href=\"https://storage.googleapis.com/tensorflow_docs/docs-l10n/site/id/tutorials/keras/text_classification_with_hub.ipynb\"><img src=\"https://www.tensorflow.org/images/download_logo_32px.png\" />Unduh notebook</a>\n",
        "  </td>\n",
        "</table>"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "Eg62Pmz3o83v"
      },
      "source": [
        "Notebook ini mengklasifikasikan review film sebagai *positif* atau *negatif* menggunakan teks dari review tersebut. Hal ini merupakan contoh dari *binary*—atau klasifikasi dua kelas, sebuah permasalahan *machine learning* yang penting dan sering ditemukan.\n",
        "\n",
        "Tutorial ini menunjukan penerapan dasar dari *transfer learning* menggunakan TensorFlow Hub dan Keras.\n",
        "\n",
        "Kita akan menggunakan [dataset IMDB](https://www.tensorflow.org/api_docs/python/tf/keras/datasets/imdb) yang terdiri atas teks review 50,000 film yang didapatkan dari [Internet Movie Database](https://www.imdb.com/). Data ini kemudian dipisah menjadi 25,000 review untuk proses training dan 25,000 untuk proses testing. Set data untuk training dan testing *seimbang*, artinya keduanya memiliki jumlah yang sama untuk review positif dan negatif.\n",
        "\n",
        "Notebook ini menggunakan [tf.keras](https://www.tensorflow.org/guide/keras), sebuah API tingkat tinggi untuk membangun dan melatih model dengan TensorFlow, dan [TensorFlow Hub](https://www.tensorflow.org/hub), sebuah *library* dan *platform* untuk melakukan *transfer learning*. Untuk tutorial teks klasifikasi menggunakan `tf.keras` lebih lanjut, lihat [MLCC Panduan Klasifikasi Teks](https://developers.google.com/machine-learning/guides/text-classification/)."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "2ew7HTbPpCJH"
      },
      "outputs": [],
      "source": [
        "import numpy as np\n",
        "import tensorflow as tf\n",
        "\n",
        "!pip install tensorflow-hub\n",
        "!pip install tensorflow-datasets\n",
        "import tensorflow_hub as hub\n",
        "import tensorflow_datasets as tfds\n",
        "\n",
        "print(\"Version: \", tf.__version__)\n",
        "print(\"Eager mode: \", tf.executing_eagerly())\n",
        "print(\"Hub version: \", hub.__version__)\n",
        "print(\"GPU is\", \"available\" if tf.config.experimental.list_physical_devices(\"GPU\") else \"NOT AVAILABLE\")"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "iAsKG535pHep"
      },
      "source": [
        "## Unduh dataset IMDB\n",
        "\n",
        "Dataset IMDB dapat diperoleh di [imdb reviews](https://github.com/tensorflow/datasets/blob/master/docs/datasets.md#imdb_reviews) atau [TensorFlow datasets](https://github.com/tensorflow/datasets). Kode berikut ini berfungsi untuk mengunduh dataset IMDB dalam komputer Anda (atau *colab runtime*)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "zXXx5Oc3pOmN"
      },
      "outputs": [],
      "source": [
        "# Split the training set into 60% and 40%, so we'll end up with 15,000 examples\n",
        "# for training, 10,000 examples for validation and 25,000 examples for testing.\n",
        "train_validation_split = tfds.Split.TRAIN.subsplit([6, 4])\n",
        "\n",
        "(train_data, validation_data), test_data = tfds.load(\n",
        "    name=\"imdb_reviews\", \n",
        "    split=(train_validation_split, tfds.Split.TEST),\n",
        "    as_supervised=True)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "l50X3GfjpU4r"
      },
      "source": [
        "## Eksplorasi data\n",
        "\n",
        "Mari kita pahami sejenak mengenai format dari data ini. Setiap data merupakan kalimat yang merepresentasikan review film dan label dari review tersebut. Kalimatnya belum di proses terlebih dahulu sebelumnya. Label merupakan bilangan integer bernilai 0 atau 1, dimana 0 menunjukkan review negatif, dan 1 review positif.\n",
        "\n",
        "Mari kita lihat 10 data pertama."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "QtTS4kpEpjbi"
      },
      "outputs": [],
      "source": [
        "train_examples_batch, train_labels_batch = next(iter(train_data.batch(10)))\n",
        "train_examples_batch"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "IFtaCHTdc-GY"
      },
      "source": [
        "Let's also print the first 10 labels."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "tvAjVXOWc6Mj"
      },
      "outputs": [],
      "source": [
        "train_labels_batch"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "LLC02j2g-llC"
      },
      "source": [
        "## Membangun Model\n",
        "\n",
        "Model neural network dibuat dengan menggabungkan beberapa layer—hal ini membutuhkan beberapa keputusan arsitektural:\n",
        "\n",
        "* Bagaimana caranya untuk merepresentasikan teks?\n",
        "* Berapa banyak layer yang akan digunakan dalam model?\n",
        "* Berapa banyak *hidden units* yang digunakan tiap layer?\n",
        "\n",
        "Dalam contoh kali ini, data input terdiri atas kalimat-kalimat. Label untuk diprediksi adalah nilai 0 atau 1.\n",
        "\n",
        "Salah satu cara untuk merepresentasikan teks adalah dengan cara mengubah kalimat menjadi vektor. Kita dapat menggunakan *pre-trained text embedding* sebagai layer pertama, yang akan memberikan tiga kelebihan:\n",
        "*   kita tidak perlu mengkhawatirkan tentang *preprocessing* teks\n",
        "*   kita dapat memperoleh keuntungan dari *transfer learning*,\n",
        "*   *embedding text* memiliki ukuran yang tetap, sehingga akan menyederhanakan proses.\n",
        "\n",
        "Dalam contoh ini kita akan menggunakan **pre-trained text embedding model** dari [TensorFlow Hub](https://www.tensorflow.org/hub) yang disebut [google/tf2-preview/gnews-swivel-20dim/1](https://tfhub.dev/google/tf2-preview/gnews-swivel-20dim/1).\n",
        "\n",
        "There are three other pre-trained models to test for the sake of this tutorial:\n",
        "Terdapat tiga model *pre-trained* lainnya yang akan dicoba dalam tutorial ini:\n",
        "\n",
        "* [google/tf2-preview/gnews-swivel-20dim-with-oov/1](https://tfhub.dev/google/tf2-preview/gnews-swivel-20dim-with-oov/1) - same as [google/tf2-preview/gnews-swivel-20dim/1](https://tfhub.dev/google/tf2-preview/gnews-swivel-20dim/1), but with 2.5% vocabulary converted to OOV buckets. This can help if vocabulary of the task and vocabulary of the model don't fully overlap.\n",
        "\n",
        "* [google/tf2-preview/nnlm-en-dim50/1](https://tfhub.dev/google/tf2-preview/nnlm-en-dim50/1) - Model yang lebih besar dengan ~1 Juta kosakata dan 50 dimensi.\n",
        "\n",
        "* [google/tf2-preview/nnlm-en-dim128/1](https://tfhub.dev/google/tf2-preview/nnlm-en-dim128/1) - Model yang jauh lebih besar lagi dengan ~1 Juta kosakata dan 128 dimensi"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "In2nDpTLkgKa"
      },
      "source": [
        "Mari kita buat layer Keras pertama yang menggunakan model Tensorflow Hub untuk menyisipkan kalimat, dan mencoba model tersebut dengan beberapa contoh input. Perhatikan bahwa berapapun panjang dari teks input, bentuk output dari *embbeding* adalah : `(num_examples, embedding_dimension)`."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "_NUbzVeYkgcO"
      },
      "outputs": [],
      "source": [
        "embedding = \"https://tfhub.dev/google/tf2-preview/gnews-swivel-20dim/1\"\n",
        "hub_layer = hub.KerasLayer(embedding, input_shape=[], \n",
        "                           dtype=tf.string, trainable=True)\n",
        "hub_layer(train_examples_batch[:3])"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "dfSbV6igl1EH"
      },
      "source": [
        "Mari kita buat model lengkapnya:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "xpKOoWgu-llD"
      },
      "outputs": [],
      "source": [
        "model = tf.keras.Sequential()\n",
        "model.add(hub_layer)\n",
        "model.add(tf.keras.layers.Dense(16, activation='relu'))\n",
        "model.add(tf.keras.layers.Dense(1, activation='sigmoid'))\n",
        "\n",
        "model.summary()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "6PbKQ6mucuKL"
      },
      "source": [
        "Layer-layer yang dihubungkan secara berurutan untuk membangun model klasifikasi:\n",
        "\n",
        "1. Layer yang pertama adalah layer TensorFlow Hub. Layer ini digunakan sebagai model tersimpan yang telah dilatih sebelumnya untuk memetakan kalimat menjadi vektor. Model *pre-trained text embedding* yang digunakan ([google/tf2-preview/gnews-swivel-20dim/1](https://tfhub.dev/google/tf2-preview/gnews-swivel-20dim/1)) memisahkan kalimat menjadi token, menyisipkan setiap token dan kemudian menggambungkan sisipan tersebut. Dimensi keluaran dari layer ini: `(num_examples, embedding_dimension)`.\n",
        "2. Vektor dengan panjang yang sama ini kemudian disalurkan melalui layer yang saling terhubung seluruhnya (`Dense`) dengan 16 *hidden unit*.\n",
        "3. Layer terakhir adalah masing-masing terhubung ke satu node output. Menggunakan fungsi aktivasi `sigmoid`, akan menghasilkan nilai antara 0 dan 1, merepresentasikan probabilitass, atau tingkat kepercayaan diri dari model.\n",
        "\n",
        "Mari lakukan kompilasi terhadap model."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "L4EqVWg4-llM"
      },
      "source": [
        "### *Loss function* dan optimizer\n",
        "\n",
        "Sebuah model memerlukan sebuah *loss function* dan sebuah optimizer sebelum proses training dilakukan. Karena ini merupakan permasalahan klasifikasi biner dan output dari model adalah probabilitas (sebuah layer satu unit dengan aktivasi sigmoid), kita akan menggunakan *loss function* berupa `binary_crossentropy`.\n",
        "\n",
        "Ini berupakan satu-satunya pilihan dari *loss function*, Anda dapat, misalnya, memilih `mean_squared_error`. Akan tetapi, secara umum, `binary_crossentropy` lebih baik ketika berhadapat dengan probablitas—fungsi ini menghitung jarak antara distribusi dari probabilitas, atau dalam kasus ini, antara distribusi yang sebenarnya dengan prediksi.\n",
        "\n",
        "Nanti, ketika kita sedang menghadapi permasalahan regresi (misalkan, memprediksi harga dari sebuah rumah), kita akan melihat bagaimana kita menggunakan *loss function* lain yang disebut mean squared error.\n",
        "\n",
        "Sekarang, konfigurasi model untuk menggunakan optimizer dan *loss function*:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "Mr0GP-cQ-llN"
      },
      "outputs": [],
      "source": [
        "model.compile(optimizer='adam',\n",
        "              loss='binary_crossentropy',\n",
        "              metrics=['accuracy'])"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "35jv_fzP-llU"
      },
      "source": [
        "## Melatih Model\n",
        "\n",
        "Latih model untuk 20 epoch dalam batch kecil berjumlah 512 sampel. Ini artinya 20 iterasi untuk seluruh sampel dalam tensor `x_train` dan `y_train`. Ketika proses training, amati nilai kerugian (*loss*) dan akurasi terhadap 10,000 sampel dari set validasi:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "tXSGrjWZ-llW"
      },
      "outputs": [],
      "source": [
        "history = model.fit(train_data.shuffle(10000).batch(512),\n",
        "                    epochs=20,\n",
        "                    validation_data=validation_data.batch(512),\n",
        "                    verbose=1)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "9EEGuDVuzb5r"
      },
      "source": [
        "## Evaluasi model\n",
        "\n",
        "Dan mari kita lihat bagaimana performa dari model. Dua nilai akan dikembalikan. Nilai kerugian (sebuah angka yang merepresentasikan error, semakin kecil nilainya semakin baik), dan akurasi."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "zOMKywn4zReN"
      },
      "outputs": [],
      "source": [
        "results = model.evaluate(test_data.batch(512), verbose=2)\n",
        "\n",
        "for name, value in zip(model.metrics_names, results):\n",
        "  print(\"%s: %.3f\" % (name, value))"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "z1iEXVTR0Z2t"
      },
      "source": [
        "Teknik yang sederhana ini memperoleh akurasi sekitar 87%. Dengan teknik yang lebih tinggi, akurasi model dapat mencapai 95%."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "5KggXVeL-llZ"
      },
      "source": [
        "## Pustaka lanjutan\n",
        "\n",
        "Untuk cara kerja yang lebih umum untuk bekerja dengan input string dan untuk analisis yang lebih detail tentang akurasi dan *loss* ketika proses training, lihat [disini](https://www.tensorflow.org/tutorials/keras/basic_text_classification)."
      ]
    }
  ],
  "metadata": {
    "colab": {
      "collapsed_sections": [],
      "name": "text_classification_with_hub.ipynb",
      "toc_visible": true
    },
    "kernelspec": {
      "display_name": "Python 3",
      "name": "python3"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}
